/*
 * Recorder - record each frame of a game. Or play it back.
 *
 * Copyright 2007 James W. Hofmann
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#if flash9
import flash3f.InputHandler;
import flash.net.SharedObject;
#else neko
import neko3f.InputHandler;
import CreepData;
#end
import haxe.Serializer;
import haxe.Unserializer;

class Recorder

{

	public static var buttonrecording : IntHash<Array<Int>>;
	public static var mouserecording : IntHash<Array<Float>>;
	public static var recordingheader : Hash<Dynamic>;
	public static var recordinglength : Int;

	public static var recordstate : Int = 0;
	public static var frame : Int = 0;
	public static var lastx : Float;
	public static var lasty : Float;
	
	#if flash9
	public static function startrecord()
	{
		buttonrecording = new IntHash();
		mouserecording = new IntHash();
		recordingheader = new Hash();
		recordstate = 1;
		recordingheader.set("version",Main.version);
		recordingheader.set("seed",Title.seed);
		recordingheader.set("username",Main.name);
		recordingheader.set("groupname",Main.group);
		recordingheader.set("gamemode",Game.cur.gamemode);
		lastx = InputHandler.cursx;
		lasty = InputHandler.cursy;
		mouserecording.set(0,[lastx,lasty]);
		frame = 0;
		recordinglength = 0;
	}
	#end

	public static function stoprecord()
	{

		recordinglength = frame;
		recordstate = 2;
		
	}

	#if flash9
	/*public static function load()
	{
		var replay:SharedObject = SharedObject.getLocal("demo");
		unserialize(replay.data.serial);
	}

	public static function save()
	{
		var replay:SharedObject = SharedObject.getLocal("demo");
		replay.setProperty("serial",serialize());
	}*/	
	#end
	
	public static function serialize() : String
	{
		var butkeys : Array<Int> = new Array();
		var moukeys : Array<Int> = new Array();
		var butdata : Array<Array<Int>> = new Array();
		var moudata : Array<Array<Float>> = new Array();
		for (n in Recorder.buttonrecording.keys())
		{
			butkeys.push(n);
			butdata.push(Recorder.buttonrecording.get(n));
		}
		for (n in Recorder.mouserecording.keys())
		{
			moukeys.push(n);
			moudata.push(Recorder.mouserecording.get(n));
		}
		var serdata = new Serializer();
		serdata.serialize([butkeys, moukeys, butdata, moudata, recordingheader, recordinglength]);
		return serdata.toString();
	}

	public static function unserialize(input : String) : Dynamic
	{
		var serdata = new Unserializer(input);

		var butkeys : Array<Int>;
		var moukeys : Array<Int>;
		var butdata : Array<Array<Int>>;
		var moudata : Array<Array<Float>>;

		{
			var data : Dynamic = serdata.unserialize();
			butkeys = data[0];
			moukeys = data[1];
			butdata = data[2];
			moudata = data[3];
			Recorder.recordingheader = data[4];
			Recorder.recordinglength = data[5];	
		}
		Recorder.buttonrecording = new IntHash();
		Recorder.mouserecording = new IntHash();
		for (n in 0...butkeys.length)
		{
			Recorder.buttonrecording.set(butkeys[n],butdata[n]);
		}
		for (n in 0...moukeys.length)
		{
			Recorder.mouserecording.set(moukeys[n],moudata[n]);
		}
		Game.cur.gamemode = recordingheader.get("gamemode");
	}
		
	public static function playback()
	{

		recordstate = 3;
		frame = 0;
	
	}
	
	public static function up()
	{
		switch(recordstate)
		{
			case(1):
			{
				var next : Array<Int> = new Array();
				if (InputHandler.click)
					next.push(0);
				if (InputHandler.wheeldelta)
					next.push(1);
				if (InputHandler.rotleftkey)
					next.push(2);
				if (InputHandler.rotrightkey)
					next.push(3);

				if (next.length>0)
					buttonrecording.set(frame, next);
					
				if (InputHandler.cursx!=lastx ||
					InputHandler.cursy!=lasty)
				{
					mouserecording.set(frame, [InputHandler.cursx,InputHandler.cursy]);
				}

				lastx = InputHandler.cursx;
				lasty = InputHandler.cursy;

				frame++;
				
				recordingheader.set("victory",WaveInterstitial.victory);
				recordingheader.set("defeat",WaveInterstitial.defeat);
				recordingheader.set("score",Game.cur.score);
				recordinglength = frame;

			}
			case(2):
			{
				recordstate = 0;
			}
			case(3):
			{
			
				InputHandler.click = false;
				InputHandler.wheeldelta = false;
				InputHandler.rotleftkey = false;
				InputHandler.rotrightkey = false;
			
				InputHandler.cursx = lastx;
				InputHandler.cursy = lasty;
			
				if (recordinglength>=frame)
				{
					if (buttonrecording.exists(frame))
					{
						var next = buttonrecording.get(frame);
						for (n in next)
						{
							switch(n)
							{
								case(0):
									InputHandler.click = true;						
								case(1):
									InputHandler.wheeldelta = true;
								case(2):
									InputHandler.rotleftkey = true;
								case(3):
									InputHandler.rotrightkey = true;
							}
								
						}
					}
					
					if (mouserecording.exists(frame))
					{
						var next = mouserecording.get(frame);
						InputHandler.cursx = next[0];
						InputHandler.cursy = next[1];
					}
					
					lastx = InputHandler.cursx;
					lasty = InputHandler.cursy;
					
				}
				else
				{
					recordstate = 0;
					#if neko
						trace("recording terminated");
						trace(["frame number ",frame]);
						trace(["score ",Game.cur.score]);
						if (Game.cur.score==recordingheader.get("score"))
						{
							Main.gameobj.verified=1; // OK
							trace("verified");
						}
						else
						{
							Main.gameobj.verified=-2; // FAIL
							trace("failed");
						}
						Main.gameobj.update();
						Recorder.dbclose();
						
						neko.Sys.exit(0);
						
					#end
				}
				
				frame++;				
				
			}

		}
	
	}

	#if neko
    public static function dbconnect()
	{        
        // initialize the connection
        var useMysql = true;
		var cnx : neko.db.Connection;
        if( !useMysql )
            cnx = neko.db.Sqlite.open("mydatabase_file.db");
        else {
            cnx = neko.db.Mysql.connect({ 
                host : CreepData.databaselocale,
                port : 3306,
                database : CreepData.databasename,
                user : CreepData.databaselogin,
                pass : CreepData.databasepass,
                socket : null
            });
        }
 
        neko.db.Manager.cnx = cnx;
        neko.db.Manager.initialize();
    }

    public static function dbclose()
	{
		neko.db.Manager.cleanup();
        neko.db.Manager.cnx.close();	
	}

	#end
	
}

class MouseEvent
{

	public var mx : Float;
	public var my : Float;

	public function new(mx, my)
	{
		this.mx = mx;
		this.my = my;
	}
	
}
